package cn.edu.cug.cs.gtl.docsrv.img.controller;


import cn.edu.cug.cs.gtl.docsrv.dict.exception.BaseException;
import cn.edu.cug.cs.gtl.docsrv.img.service.ImgService;
import cn.edu.cug.cs.gtl.docsrv.img.catalog.CatalogTree; 
import cn.edu.cug.cs.gtl.docsrv.img.service.ImgService;
import cn.edu.cug.cs.gtl.extractor.ShapeExtractor;
import cn.edu.cug.cs.gtl.mybatis.mapper.img.ImgAll;
import cn.edu.cug.cs.gtl.mybatis.mapper.img.ImgCatalog;
import cn.edu.cug.cs.gtl.mybatis.mapper.img.ImgItem; 
import cn.edu.cug.cs.gtl.mybatis.metadata.ImgUtils; 
import cn.edu.cug.cs.gtl.protos.Document;


import cn.edu.cug.cs.gtl.protos.DocumentList;
import cn.edu.cug.cs.gtl.protos.Tree;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.google.protobuf.util.JsonFormat;
import org.geotools.geojson.geom.GeometryJSON;
import org.locationtech.jts.geom.Envelope;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;

@RestController
@CrossOrigin
@RequestMapping(value = "/api")
public class ImgController {
    @Autowired
    ImgService imgService;
    /** 
     服务名称：addImg
     功能描述：单个本地Img文件入库
     接口描述： /api/img/addImg
     传入参数：
     ImgAll  img；前端传入ImgAll的JSON对象
     返回值：
     成功返回true , 否则返回false
     调用示例：
     */
    @PostMapping(value = "/img/addImg")
    public void addImg(
            @RequestParam(value = "data") String data){
        try {
            ImgAll imgAll = JSON.parseObject(data,ImgAll.class);
            if(imgAll!=null)
                imgService.addImg(imgAll);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /**
     服务名称：addImgs
     功能描述：多个本地IMG文件入库
     接口描述： /api/img/ addImgs
     传入参数：
     List<ImgAll>  imgs；前端传入ImgAll列表的JSON对象
     返回值：
     成功返回true , 否则返回false
     调用示例：
     */
    @PostMapping(value = "/img/addImgs")
    public void addImgs(
            @RequestParam(value = "data") String data){
        try {
            ImgAllList imgAllList = JSON.parseObject(data,ImgAllList.class);
            if(imgAllList!=null)
                imgService.addImgs(imgAllList.getImgAllList());
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：addFromRawDB
     功能描述：从原始数据库中提取指定类型的图像文件入库
     接口描述： /api/img/addFromRawDB
     传入参数：
     String imgType   图像类型，文件后缀；
     返回值：
     成功返回true , 否则返回false
     调用示例：
     */
    @PostMapping(value = "/img/addFromRawDB")
    public void addFromRawDB(@RequestParam(value = "imgType") String imgType){
        try {
            imgService.addFromRawDB();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /** 
     服务名称：getImgByName
     功能描述：图像数据库中提取指定名称的图像文件
     接口描述： /api/img/getImgByName
     传入参数：
     String imgName   图像名称；
     返回值：
     List<ImgAll> imgAllList 的JSON字符串
     调用示例：
     */
    @GetMapping(value = "/img/getImgByName")
    public List<ImgAll> getImgByName(@RequestParam(value = "imgName") String imgName){
        try {
            return imgService.getImgByName(imgName);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：getImgByEnTitle
     功能描述：图像数据库中提取指定英文名称的图像文件
     接口描述： /api/img/ getImgByEnTitle
     传入参数：
     String imgEnTitle ；
     返回值：
     List<ImgAll> imgAllList 的JSON字符串
     调用示例：
     */
    @GetMapping(value = "/img/getImgByEnTitle")
    public List<ImgAll> getImgByEnTitle(@RequestParam(value = "imgEnTitle") String imgEnTitle){
        try {
            return imgService.getImgByEnTitle(imgEnTitle);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：getImgByCnTitle
     功能描述：图像数据库中提取指定中文名称的图像文件
     接口描述： /api/img/ getImgByCnTitle
     传入参数：
     String imgCnTitle ；
     返回值：
     List<ImgAll> imgAllList 的JSON字符串
     调用示例：
     */
    @GetMapping(value = "/img/getImgByCnTitle")
    public List<ImgAll> getImgByCnTitle(@RequestParam(value = "imgCnTitle") String imgCnTitle){
        try {
            return imgService.getImgByEnTitle(imgCnTitle);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：getImgByInternalId
     功能描述：图像数据库中提取指定ID的图像文件
     接口描述： /api/img/getImgByInternalId
     传入参数：
     long imgInternalId；
     返回值：
     ImgAll  img     ; ImgAll的JSON字符串
     调用示例：
     */
    @GetMapping(value = "/img/getImgByInternalId")
    public ImgAll getImgByInternalId(@RequestParam(value = "imgInternalId") long imgInternalId){
        try {
            return imgService.getImgByInternalId(BigDecimal.valueOf(imgInternalId));
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：getImgByBoundingBox
     功能描述：图像数据库中提取指定范围的图像
     接口描述： /api/img/getImgByBoundingBox
     传入参数：
     String bb；//minx,maxx,miny,maxy  数字之间逗号分隔
     String mask; //intersect 相交的图像； 或  contains 包含的图像
     返回值：
     List<ImgAll> imgAllList 的JSON字符串
     调用示例：
     */
    @GetMapping(value = "/img/getImgByBoundingBox")
    public List<ImgAll> getImgByBoundingBox(
            @RequestParam(value = "imgBoundingBpx") String imgBoundingBpx,
            @RequestParam(value = "mask") String mask ){
        try {

            return imgService.getImgByBoundingBox(imgBoundingBpx,mask);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：deleteImgByInternalId
     功能描述：删除图像数据库中指定ID的图像
     接口描述： /api/img/deleteImgByInternalId
     传入参数：
     long internalId；
     返回值：
     成功返回true , 否则返回false
     调用示例：
     */
    @PostMapping(value = "/img/deleteImgByInternalId")
    public void deleteImgByInternalId(@RequestParam(value = "imgInternalId") long imgInternalId){
        try {
            imgService.deleteImgByInternalId(BigDecimal.valueOf(imgInternalId));
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }



     

    /** 
     * 服务名称：getEnvelopeByImgInternalId
     * 功能描述：图像数据库中提取指定范围的几何对象
     * 接口描述： /api/img/getEnvelopeByImgInternalId
     * 传入参数：
     * long imgInternalId
     * 返回值：
     * Envelope
     * 调用示例：
     *
     * @param imgInternalId
     */
    @GetMapping(value = "/img/getEnvelopeByImgInternalId")
    public String getEnvelopeByImgInternalId(
            @RequestParam(value = "imgInternalId") long imgInternalId) {
        Envelope e= imgService.getEnvelopeByImgInternalId(BigDecimal.valueOf(imgInternalId));
        GeometryJSON geometryJSON = new GeometryJSON();
        return geometryJSON.toString(e);
    }

    /** 
     * 服务名称：getImgCatalogs
     * 功能描述：图像数据库中提取所有分类
     * 接口描述： /api/img/getImgCatalogs
     * 传入参数：
     * 返回值：
     * List<ImgCatalog> catalogs
     * 调用示例：
     */
    @GetMapping(value = "/img/getImgCatalogs")
    public List<ImgCatalog> getImgCatalogs() {
        return imgService.getImgCatalogs();
    }

 
    /** 
     服务名称：getDocumentByImgInternalId
     功能描述：图像数据库中提取指定Img文档
     接口描述： /api/img/getDocumentByImgInternalId
     传入参数：
     long imgInternalId
     返回值：
     Document doc;
     其中，每个Feature的GeoJSON字符串为Document的一个content；
     其他的不为空的字段为该Img文档的元数据。
     调用示例：
     http://localhost:8090/api/img/getDocumentByImgInternalId?imgInternalId=3
     */
    @GetMapping(value = "/img/getDocumentByImgInternalId")
    public byte[] getDocumentByImgInternalId(
            @RequestParam(value = "imgInternalId") long imgInternalId){
        try {
            Document d= imgService.getDocumentByImgInternalId(BigDecimal.valueOf(imgInternalId));
            if(d!=null)
                return d.toByteArray();
            else
                return null;
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：addImgDocument
     功能描述：单个本地Img文件入库,采用Document传递
     接口描述： /api/img/addImgDocument
     传入参数：
     Document  img；前端传入的和ShapAll对应的Document的字节数组
     返回值：
     成功返回true , 否则返回false
     调用示例：
     */
    @PostMapping(value = "/img/addImgDocument")
    public void addImgDocument(@RequestBody  byte[] data){
        try {
            Document d = Document.parseFrom(data);
            if(d!=null){
                ImgAll imgAll = ImgUtils.convert(d);
                if(imgAll!=null)
                    imgService.addImg(imgAll);
            }
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /** 
     服务名称：addImgDocuments
     功能描述：多个IMG文档入库
     接口描述： /api/img/addImgDocuments
     传入参数：
     DocumentList  imgs；DocumentList的字节数组
     返回值：
     成功返回true , 否则返回false
     调用示例：
     */
    @PostMapping(value = "/img/addImgDocuments")
    public void addImgDocuments(@RequestBody  byte[] data){
        try {
            DocumentList dl = DocumentList.parseFrom(data);
            for(Document d:dl.getElementList()){
                if(d!=null){
                    ImgAll imgAll = ImgUtils.convert(d);
                    if(imgAll!=null)
                        imgService.addImg(imgAll);
                }
            }
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }



    /** 
     服务名称：getDocumentsByImgName
     功能描述：图像数据库中提取指定名称的图像文档
     接口描述： /api/img/getDocumentsByImgName
     传入参数：
     String  imgName；
     返回值：
     DocumentList  imgs；DocumentList的字节数组；
     其中每个Document的Contents存放1至多个FeatureJSON
     调用示例：
     */
    @GetMapping(value = "/img/getDocumentsByImgName")
    public byte[] getDocumentsByImgName(@RequestParam(value = "imgName") String imgName){
        try {
            List<ImgAll> imgAllList= imgService.getImgByName(imgName);
            DocumentList.Builder documentListBuilder = DocumentList.newBuilder();
            for (ImgAll imgAll:imgAllList){
                Document doc = ImgUtils.convert(imgAll);
                documentListBuilder.addElement(doc);
            }
            return documentListBuilder.build().toByteArray();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /**
     服务名称：getDocumentsByImgEnTitle
     功能描述：图像数据库中提取指定英文名称的图像文件
     接口描述： /api/img/getDocumentsByImgEnTitle
     传入参数：
     String imgEnTitle ；
     返回值：
     DocumentList  imgs；DocumentList的字节数组；
     其中每个Document的Contents存放1至多个FeatureJSON
     调用示例：
     */
    @GetMapping(value = "/img/getDocumentsByImgEnTitle")
    public byte[] getDocumentsByImgEnTitle(@RequestParam(value = "imgEnTitle") String imgEnTitle){
        try {
            List<ImgAll> imgAllList= imgService.getImgByEnTitle(imgEnTitle);
            DocumentList.Builder documentListBuilder = DocumentList.newBuilder();
            for (ImgAll imgAll:imgAllList){
                Document doc = ImgUtils.convert(imgAll);
                documentListBuilder.addElement(doc);
            }
            return documentListBuilder.build().toByteArray();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /**
     服务名称：getDocumentsByImgCnTitle
     功能描述：图像数据库中提取指定中文名称的图像文档
     接口描述： /api/img/getDocumentsByImgCnTitle
     传入参数：
     String imgCnTitle ；
     返回值：
     DocumentList  imgs；DocumentList的字节数组；
     其中每个Document的Contents存放1至多个FeatureJSON
     调用示例：
     */
    @GetMapping(value = "/img/getDocumentsByImgCnTitle")
    public byte[] getDocumentsByImgCnTitle(@RequestParam(value = "imgCnTitle") String imgCnTitle){
        try {
            List<ImgAll> imgAllList= imgService.getImgByCnTitle(imgCnTitle);
            DocumentList.Builder documentListBuilder = DocumentList.newBuilder();
            for (ImgAll imgAll:imgAllList){
                Document doc = ImgUtils.convert(imgAll);
                documentListBuilder.addElement(doc);
            }
            return documentListBuilder.build().toByteArray();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /**
     服务名称：getDocumentsByCatalogInternalId
     功能描述：图像数据库中提取指定分类ID的所有图像文档
     接口描述：/api/img/getDocumentsByCatalogInternalId
     传入参数：
     long catalogInternalId
     返回值：
     DocumentList docList;
     其中，每个Feature的GeoJSON字符串为Document的一个content；
     其他的不为空的字段为该Img文档的元数据。
     调用示例：
     http://localhost:8090/api/img/getDocumentsByCatalogInternalId?catalogInternalId=3
     */
    @GetMapping(value = "/img/getDocumentsByCatalogInternalId")
    public byte[] getDocumentsByCatalogInternalId(
            @RequestParam(value = "catalogInternalId") long catalogInternalId){
        try {
            DocumentList dl= imgService.getDocumentsByCatalogInternalId(BigDecimal.valueOf(catalogInternalId));
            if(dl!=null) {
                return dl.toByteArray();
            }
            else
                return null;
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /**
     服务名称：getCatalogTree
     功能描述：图像数据库中分类树
     接口描述：/api/img/getCatalogTree
     传入参数：
     返回值：Tree   tree。
     调用示例：
     http://localhost:8090/api/img/getCatalogTree
     */
    @GetMapping(value = "/img/getCatalogTree")
    public byte[] getCatalogTree(){
        try {
            CatalogTree catalogTree = imgService.getCatalogTree();
            if(catalogTree!=null){
                Tree tree = catalogTree.cloneTree();
                if(tree!=null)
                    return tree.toByteArray();
            }
            return null;
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     服务名称：getCatalogTreeJSON
     功能描述：图像数据库中分类树的JSON
     接口描述：/api/img/getCatalogTreeJSON
     传入参数：
     返回值：Tree   tree 对于的JSON
     调用示例：
     http://localhost:8090/api/img/getCatalogTreeJSON
     */
    @GetMapping(value = "/img/getCatalogTreeJSON")
    public String getCatalogTreeJSON(){
        try {
            CatalogTree catalogTree = imgService.getCatalogTree();
            if(catalogTree!=null){
                Tree tree = catalogTree.cloneTree();
                if(tree!=null){
                    String sss = JsonFormat.printer().print(tree.toBuilder());
                    return sss;
                }
            }
            return null;
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }



    /**
     服务名称：getImgInternalIdsByCatalogInternalId
     功能描述：图像数据库中提取指定分类ID的所有图像文档的ID
     接口描述：/api/img/getImgInternalIdsByCatalogInternalId
     传入参数：
     long catalogInternalId
     返回值： String ImgInternalIds,
     JSONArray
     例如 "[1,2,3,4,5,6]"
     调用示例：
     http://localhost:8090/api/img/getImgInternalIdsByCatalogInternalId?catalogInternalId=3
     */
    @GetMapping(value = "/img/getImgInternalIdsByCatalogInternalId")
    public String getImgInternalIdsByCatalogInternalId(
            @RequestParam(value = "catalogInternalId") long catalogInternalId){
        try {
            List<BigDecimal> ls = imgService.getImgInternalIdsByCatalogInternalId(BigDecimal.valueOf(catalogInternalId));
            if(ls==null && ls.isEmpty()) return new String();

            int c = ls.size();
            long [] rs = new long[c];
            int i=0;
            for(BigDecimal b: ls) {
                rs[i] = b.longValue();
                ++i;
            }
            return JSONArray.toJSONString(rs);
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }


    /**
     服务名称：getGeoJSONByImgInternalId
     功能描述：图像数据库中提取指定Img文档的GeoJSON
     接口描述： /api/img/getGeoJSONByImgInternalId
     传入参数：
     long imgInternalId
     返回值：
     GeoJSON;
     调用示例：
     http://localhost:8090/api/img/getGeoJSONByImgInternalId?imgInternalId=3
     */
    @GetMapping(value = "/img/getGeoJSONByImgInternalId")
    public String getGeoJSONByImgInternalId(
            @RequestParam(value = "imgInternalId") long imgInternalId){
        try {
            ImgAll imgAll = imgService.getImgByInternalId(BigDecimal.valueOf(imgInternalId));
            if (imgAll==null) return new String();
            return ShapeExtractor.parseToGeoJSON(imgAll.getImgRawBytes());
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

}
